package com.itheima.sh.esdemo;

import com.alibaba.fastjson.JSON;
import com.itheima.sh.esdemo.pojo.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.naming.directory.SearchResult;
import java.io.IOException;
import java.util.Map;

public class SearchDemo {

    @Test
    public void searchamath() throws Exception {
//        1. 创建SearchSourceBuilder对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        1. 添加查询条件QueryBuilders
        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
//        2. 如：添加排序、分页等其它条件
        sourceBuilder.query(matchAllQueryBuilder);
//        2. 创建SearchRequest对象，并制定索引库名称
        SearchRequest request = new SearchRequest("user");
//        3. 添加SearchSourceBuilder对象到SearchRequest对象source中
        request.source(sourceBuilder);
//        4. 发起请求，得到结果
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//        5. 解析结果SearchResponse
//        1. 获取总条数
        long value = response.getHits().getTotalHits().value;
        System.out.println("总计录数=" + value);
//        2. 获取SearchHits数组，并遍历
        SearchHit[] hits = response.getHits().getHits();
//                - 获取其中的_source，是JSON数据
        //                - 把_source反序列化为User对象
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            System.out.println(user);
        }


    }

    //    term查询
    @Test
    public void termSearch() throws Exception {
        //获得SearchSourchBuilder对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //添加查询条件
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "张萨姆0");
        sourceBuilder.query(termQueryBuilder);
        //创建SearchRequest对象指定索引库，
        SearchRequest request = new SearchRequest("user");
        //把查询的对象SearchSourceBuilder放到SearchRequest中的source资源中。
        request.source(sourceBuilder);
        //发起请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //处理响应结果
        //获得总条数
        long value = response.getHits().getTotalHits().value;
        System.out.println("总计录数=" + value);
        //获得的数据是Json字符串，序列化对象
        SearchHits hits = response.getHits();
        SearchHit[] hits1 = hits.getHits();
        for (SearchHit fields : hits1) {
            String sourceAsString = fields.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            System.out.println(user);

        }
    }

    //math分词查询,对查询条件分词，取or
    @Test
    public void mathSearch() throws Exception {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("note", "唱歌");
        sourceBuilder.query(matchQueryBuilder);
        SearchRequest searchRequest = new SearchRequest("user");
        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        long value = response.getHits().getTotalHits().value;
        System.out.println("总计录数=" + value);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            System.out.println(user);
        }
    }

    //模糊查询fuzzy，
    @Test
    public void fuzzySearch() throws Exception {
        //创建SearchSourchBuild对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //指定查询条件
        FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("note", "传智播客");
        sourceBuilder.query(fuzzyQueryBuilder);
        //创建查询对象
        SearchRequest request = new SearchRequest("user");
        //把查询条件封装到对象中
        request.source(sourceBuilder);
        //发送请求
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        long value = search.getHits().getTotalHits().value;
        System.out.println("结果数为=" + value);
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            System.out.println(user);
        }
    }

    //范围查询&排序
    @Test
    public void rangSortsEARCH() throws Exception {
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(22).lte(27);
        sourceBuilder.sort("id", SortOrder.DESC);
        sourceBuilder.query(rangeQueryBuilder);
        SearchRequest request = new SearchRequest("user").source(sourceBuilder);
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        long value = search.getHits().getTotalHits().value;
        System.out.println("总结过数=" + value);
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            System.out.println(user);
        }


    }
//多条件查询query_string
    @Test
    public void queryStringSearch() throws Exception {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("同学小红").field("name").field("note").defaultOperator(Operator.AND);
        sourceBuilder.query(queryStringQueryBuilder);
        SearchRequest request =new SearchRequest("user");
        request.source(sourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        long value = response.getHits().getTotalHits().value;
        System.out.println("总结果数=" + value);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            System.out.println(user);
        }
    }
//复合查询
    @Test
    public void boolquerySearch() throws Exception {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "小红");
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("note", "同学");
        RangeQueryBuilder age = QueryBuilders.rangeQuery("age").gte(20).lt(38);
        boolQueryBuilder.should(termQueryBuilder);
        boolQueryBuilder.must(matchQueryBuilder).must(age);
        MatchQueryBuilder matchQueryBuilder1 = QueryBuilders.matchQuery("note", "山顶");
        boolQueryBuilder.filter(matchQueryBuilder1);
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest request = new SearchRequest("user").source(sourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        long value = response.getHits().getTotalHits().value;
        System.out.println("总结果数=" + value);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            System.out.println(user);
        }
    }

//分页查询 form
    @Test
    public void formSearch() throws Exception {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("note", "同学");
        int from =0;
        int size =3;
        sourceBuilder.query(matchQueryBuilder).from(from).size(size);
        sourceBuilder.sort("age", SortOrder.ASC);
        SearchRequest request =new SearchRequest("user");
        request.source(sourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        long value = response.getHits().getTotalHits().value;
        System.out.println("总结果数=" + value);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            System.out.println(user);
        }
    }
//    高亮查询
    @Test
    public void highSearch() throws Exception {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("note", "黑马");
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("note").preTags("<font color ='red>").postTags("</font>");
        sourceBuilder.query(matchQueryBuilder).highlighter(highlightBuilder);
        SearchRequest request =new SearchRequest("user");
        request.source(sourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        long value = response.getHits().getTotalHits().value;
        System.out.println("总结过数=" + value);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            User user = JSON.parseObject(sourceAsString, User.class);
            HighlightField note = hit.getHighlightFields().get("note");
            //得到高亮片段。es中当高亮字数达到一定的程度会拆分，
            Text[] fragments = note.getFragments();
            //拼接高亮片段
            String join = StringUtils.join(fragments);
            if (StringUtils.isNotBlank(join)) {
                user.setNote(join);
            }
            System.out.println(user);
        }
    }





































    private RestHighLevelClient client;

    @Before
    public void init() throws IOException {
        //创建es客户端
        client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.200.150", 9200, "http")));
    }

    @After
    public void testrestclose() {
        try {
            if (client != null) {
                client.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
